//! # 消息类型定义
//!
//! 定义消息总线系统中的消息类型、元数据和序列化机制

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use uuid::Uuid;

use crate::error::{MessageBusError, MessageBusResult};

/// 消息类型枚举
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessageType {
    /// 事件消息 - 用于事件驱动架构
    Event,
    /// 命令消息 - 用于命令模式和 CQRS
    Command,
    /// 查询消息 - 用于查询处理
    Query,
    /// 通知消息 - 用于系统通知
    Notification,
    /// 回复消息 - 用于请求-响应模式
    Reply,
}

impl Default for MessageType {
    fn default() -> Self {
        MessageType::Event
    }
}

/// 消息优先级
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum MessagePriority {
    Low = 1,
    Normal = 2,
    High = 3,
    Critical = 4,
}

impl Default for MessagePriority {
    fn default() -> Self {
        MessagePriority::Normal
    }
}

/// 消息持久化级别
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PersistenceLevel {
    /// 不持久化（仅内存）
    None,
    /// 磁盘持久化
    Disk,
    /// 复制持久化
    Replicated,
}

impl Default for PersistenceLevel {
    fn default() -> Self {
        PersistenceLevel::None
    }
}

/// 消息属性
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageAttributes {
    /// 消息类型
    pub message_type: MessageType,
    /// 优先级
    pub priority: MessagePriority,
    /// 持久化级别
    pub persistence: PersistenceLevel,
    /// 过期时间（TTL）
    pub expires_at: Option<DateTime<Utc>>,
    /// 重试次数
    pub retry_count: u32,
    /// 最大重试次数
    pub max_retries: u32,
    /// 延迟投递时间
    pub delay_until: Option<DateTime<Utc>>,
    /// 自定义属性
    pub custom: HashMap<String, String>,
}

impl Default for MessageAttributes {
    fn default() -> Self {
        Self {
            message_type: MessageType::default(),
            priority: MessagePriority::default(),
            persistence: PersistenceLevel::default(),
            expires_at: None,
            retry_count: 0,
            max_retries: 3,
            delay_until: None,
            custom: HashMap::new(),
        }
    }
}

/// 消息元数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageMetadata {
    /// 消息唯一标识
    pub id: Uuid,
    /// 主题
    pub topic: String,
    /// 关联 ID（用于追踪）
    pub correlation_id: Option<Uuid>,
    /// 回复主题
    pub reply_to: Option<String>,
    /// 发送者
    pub sender: Option<String>,
    /// 接收者
    pub receiver: Option<String>,
    /// 创建时间
    pub created_at: DateTime<Utc>,
    /// 发送时间
    pub sent_at: Option<DateTime<Utc>>,
    /// 接收时间
    pub received_at: Option<DateTime<Utc>>,
    /// 消息属性
    pub attributes: MessageAttributes,
    /// 追踪头
    pub trace_headers: HashMap<String, String>,
}

impl MessageMetadata {
    /// 创建新的消息元数据
    pub fn new(topic: impl Into<String>) -> Self {
        Self {
            id: Uuid::new_v4(),
            topic: topic.into(),
            correlation_id: None,
            reply_to: None,
            sender: None,
            receiver: None,
            created_at: Utc::now(),
            sent_at: None,
            received_at: None,
            attributes: MessageAttributes::default(),
            trace_headers: HashMap::new(),
        }
    }

    /// 设置关联 ID
    pub fn with_correlation_id(mut self, correlation_id: Uuid) -> Self {
        self.correlation_id = Some(correlation_id);
        self
    }

    /// 设置回复主题
    pub fn with_reply_to(mut self, reply_to: impl Into<String>) -> Self {
        self.reply_to = Some(reply_to.into());
        self
    }

    /// 设置发送者
    pub fn with_sender(mut self, sender: impl Into<String>) -> Self {
        self.sender = Some(sender.into());
        self
    }

    /// 设置接收者
    pub fn with_receiver(mut self, receiver: impl Into<String>) -> Self {
        self.receiver = Some(receiver.into());
        self
    }

    /// 设置消息类型
    pub fn with_message_type(mut self, message_type: MessageType) -> Self {
        self.attributes.message_type = message_type;
        self
    }

    /// 设置优先级
    pub fn with_priority(mut self, priority: MessagePriority) -> Self {
        self.attributes.priority = priority;
        self
    }

    /// 设置持久化级别
    pub fn with_persistence(mut self, persistence: PersistenceLevel) -> Self {
        self.attributes.persistence = persistence;
        self
    }

    /// 设置过期时间
    pub fn with_expires_at(mut self, expires_at: DateTime<Utc>) -> Self {
        self.attributes.expires_at = Some(expires_at);
        self
    }

    /// 设置最大重试次数
    pub fn with_max_retries(mut self, max_retries: u32) -> Self {
        self.attributes.max_retries = max_retries;
        self
    }

    /// 设置延迟投递时间
    pub fn with_delay_until(mut self, delay_until: DateTime<Utc>) -> Self {
        self.attributes.delay_until = Some(delay_until);
        self
    }

    /// 添加自定义属性
    pub fn with_custom_attribute(
        mut self, 
        key: impl Into<String>, 
        value: impl Into<String>
    ) -> Self {
        self.attributes.custom.insert(key.into(), value.into());
        self
    }

    /// 添加追踪头
    pub fn with_trace_header(
        mut self, 
        key: impl Into<String>, 
        value: impl Into<String>
    ) -> Self {
        self.trace_headers.insert(key.into(), value.into());
        self
    }

    /// 检查消息是否过期
    pub fn is_expired(&self) -> bool {
        if let Some(expires_at) = self.attributes.expires_at {
            Utc::now() > expires_at
        } else {
            false
        }
    }

    /// 检查是否应该延迟投递
    pub fn should_delay(&self) -> bool {
        if let Some(delay_until) = self.attributes.delay_until {
            Utc::now() < delay_until
        } else {
            false
        }
    }

    /// 检查是否可以重试
    pub fn can_retry(&self) -> bool {
        self.attributes.retry_count < self.attributes.max_retries
    }

    /// 增加重试次数
    pub fn increment_retry(&mut self) {
        self.attributes.retry_count += 1;
    }

    /// 标记为已发送
    pub fn mark_sent(&mut self) {
        self.sent_at = Some(Utc::now());
    }

    /// 标记为已接收
    pub fn mark_received(&mut self) {
        self.received_at = Some(Utc::now());
    }

    /// 设置追踪头（可变引用）
    pub fn set_header(&mut self, key: String, value: String) {
        self.trace_headers.insert(key, value);
    }

    /// 获取追踪头
    pub fn get_header(&self, key: &str) -> Option<&String> {
        self.trace_headers.get(key)
    }
}

impl Default for MessageMetadata {
    fn default() -> Self {
        Self {
            id: Uuid::new_v4(),
            topic: String::new(),
            correlation_id: None,
            reply_to: None,
            sender: None,
            receiver: None,
            created_at: Utc::now(),
            sent_at: None,
            received_at: None,
            attributes: MessageAttributes::default(),
            trace_headers: HashMap::new(),
        }
    }
}

/// 消息体
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
    /// 元数据
    pub metadata: MessageMetadata,
    /// 消息载荷
    pub payload: Value,
}

impl Message {
    /// 创建新消息
    pub fn new(topic: impl Into<String>, payload: Value) -> Self {
        Self {
            metadata: MessageMetadata::new(topic),
            payload,
        }
    }

    /// 创建事件消息
    pub fn event(topic: impl Into<String>, payload: Value) -> Self {
        Self {
            metadata: MessageMetadata::new(topic).with_message_type(MessageType::Event),
            payload,
        }
    }

    /// 创建命令消息
    pub fn command(topic: impl Into<String>, payload: Value) -> Self {
        Self {
            metadata: MessageMetadata::new(topic).with_message_type(MessageType::Command),
            payload,
        }
    }

    /// 创建查询消息
    pub fn query(topic: impl Into<String>, payload: Value) -> Self {
        Self {
            metadata: MessageMetadata::new(topic).with_message_type(MessageType::Query),
            payload,
        }
    }

    /// 创建通知消息
    pub fn notification(topic: impl Into<String>, payload: Value) -> Self {
        Self {
            metadata: MessageMetadata::new(topic).with_message_type(MessageType::Notification),
            payload,
        }
    }

    /// 创建回复消息
    pub fn reply(
        topic: impl Into<String>, 
        payload: Value,
        correlation_id: Uuid
    ) -> Self {
        Self {
            metadata: MessageMetadata::new(topic)
                .with_message_type(MessageType::Reply)
                .with_correlation_id(correlation_id),
            payload,
        }
    }

    /// 获取消息 ID
    pub fn id(&self) -> Uuid {
        self.metadata.id
    }

    /// 获取主题
    pub fn topic(&self) -> &str {
        &self.metadata.topic
    }

    /// 获取载荷
    pub fn payload(&self) -> &Value {
        &self.payload
    }

    /// 获取可变载荷
    pub fn payload_mut(&mut self) -> &mut Value {
        &mut self.payload
    }

    /// 获取元数据
    pub fn metadata(&self) -> &MessageMetadata {
        &self.metadata
    }

    /// 获取可变元数据
    pub fn metadata_mut(&mut self) -> &mut MessageMetadata {
        &mut self.metadata
    }

    /// 设置元数据
    pub fn with_metadata(mut self, metadata: MessageMetadata) -> Self {
        self.metadata = metadata;
        self
    }

    /// 序列化为字节
    pub fn to_bytes(&self) -> MessageBusResult<Vec<u8>> {
        serde_json::to_vec(self).map_err(|e| MessageBusError::serialization_error(e.to_string()))
    }

    /// 从字节反序列化
    pub fn from_bytes(bytes: &[u8]) -> MessageBusResult<Self> {
        serde_json::from_slice(bytes).map_err(|e| MessageBusError::deserialization_error(e.to_string()))
    }

    /// 序列化为字符串
    pub fn to_string(&self) -> MessageBusResult<String> {
        serde_json::to_string(self).map_err(|e| MessageBusError::serialization_error(e.to_string()))
    }

    /// 从字符串反序列化
    pub fn from_string(s: &str) -> MessageBusResult<Self> {
        serde_json::from_str(s).map_err(|e| MessageBusError::deserialization_error(e.to_string()))
    }

    /// 获取消息大小（字节）
    pub fn size(&self) -> usize {
        self.to_bytes().map(|bytes| bytes.len()).unwrap_or(0)
    }

    /// 验证消息
    pub fn validate(&self) -> MessageBusResult<()> {
        // 检查主题是否为空
        if self.metadata.topic.is_empty() {
            return Err(MessageBusError::message_format_error("主题不能为空"));
        }

        // 检查消息是否过期
        if self.metadata.is_expired() {
            return Err(MessageBusError::message_format_error("消息已过期"));
        }

        Ok(())
    }

    /// 克隆消息并生成新的 ID
    pub fn clone_with_new_id(&self) -> Self {
        let mut new_message = self.clone();
        new_message.metadata.id = Uuid::new_v4();
        new_message.metadata.created_at = Utc::now();
        new_message.metadata.sent_at = None;
        new_message.metadata.received_at = None;
        new_message
    }
}

/// 消息构建器
#[derive(Debug, Default)]
pub struct MessageBuilder {
    topic: Option<String>,
    payload: Option<Value>,
    metadata: MessageMetadata,
}

impl MessageBuilder {
    /// 创建新的消息构建器
    pub fn new() -> Self {
        Self::default()
    }

    /// 设置主题
    pub fn topic(mut self, topic: impl Into<String>) -> Self {
        let topic = topic.into();
        self.metadata.topic = topic.clone();
        self.topic = Some(topic);
        self
    }

    /// 设置载荷
    pub fn payload(mut self, payload: Value) -> Self {
        self.payload = Some(payload);
        self
    }

    /// 设置消息类型
    pub fn message_type(mut self, message_type: MessageType) -> Self {
        self.metadata.attributes.message_type = message_type;
        self
    }

    /// 设置优先级
    pub fn priority(mut self, priority: MessagePriority) -> Self {
        self.metadata.attributes.priority = priority;
        self
    }

    /// 设置关联 ID
    pub fn correlation_id(mut self, correlation_id: Uuid) -> Self {
        self.metadata.correlation_id = Some(correlation_id);
        self
    }

    /// 设置回复主题
    pub fn reply_to(mut self, reply_to: impl Into<String>) -> Self {
        self.metadata.reply_to = Some(reply_to.into());
        self
    }

    /// 设置发送者
    pub fn sender(mut self, sender: impl Into<String>) -> Self {
        self.metadata.sender = Some(sender.into());
        self
    }

    /// 设置接收者
    pub fn receiver(mut self, receiver: impl Into<String>) -> Self {
        self.metadata.receiver = Some(receiver.into());
        self
    }

    /// 构建消息
    pub fn build(self) -> MessageBusResult<Message> {
        let topic = self.topic.ok_or_else(|| 
            MessageBusError::message_format_error("主题是必需的")
        )?;
        
        let payload = self.payload.unwrap_or(Value::Null);
        
        let mut metadata = self.metadata;
        metadata.topic = topic;
        
        let message = Message { metadata, payload };
        message.validate()?;
        
        Ok(message)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;

    #[test]
    fn test_message_creation() {
        let payload = json!({"user_id": 123, "action": "login"});
        let message = Message::new("user.events.login", payload.clone());
        
        assert_eq!(message.topic(), "user.events.login");
        assert_eq!(message.payload(), &payload);
        assert_eq!(message.metadata.attributes.message_type, MessageType::Event);
    }

    #[test]
    fn test_message_types() {
        let payload = json!({"test": "data"});
        
        let event = Message::event("test.event", payload.clone());
        assert_eq!(event.metadata.attributes.message_type, MessageType::Event);
        
        let command = Message::command("test.command", payload.clone());
        assert_eq!(command.metadata.attributes.message_type, MessageType::Command);
        
        let query = Message::query("test.query", payload.clone());
        assert_eq!(query.metadata.attributes.message_type, MessageType::Query);
        
        let notification = Message::notification("test.notification", payload);
        assert_eq!(notification.metadata.attributes.message_type, MessageType::Notification);
    }

    #[test]
    fn test_message_builder() {
        let correlation_id = Uuid::new_v4();
        let message = MessageBuilder::new()
            .topic("test.topic")
            .payload(json!({"test": "data"}))
            .message_type(MessageType::Command)
            .priority(MessagePriority::High)
            .correlation_id(correlation_id)
            .sender("test-service")
            .build()
            .unwrap();
        
        assert_eq!(message.topic(), "test.topic");
        assert_eq!(message.metadata.attributes.message_type, MessageType::Command);
        assert_eq!(message.metadata.attributes.priority, MessagePriority::High);
        assert_eq!(message.metadata.correlation_id, Some(correlation_id));
        assert_eq!(message.metadata.sender.as_deref(), Some("test-service"));
    }

    #[test]
    fn test_message_serialization() {
        let payload = json!({"user_id": 123});
        let message = Message::new("test.topic", payload);
        
        let bytes = message.to_bytes().unwrap();
        let deserialized = Message::from_bytes(&bytes).unwrap();
        
        assert_eq!(message.id(), deserialized.id());
        assert_eq!(message.topic(), deserialized.topic());
        assert_eq!(message.payload(), deserialized.payload());
    }

    #[test]
    fn test_message_validation() {
        let mut message = Message::new("", json!({}));
        assert!(message.validate().is_err());
        
        message.metadata.topic = "valid.topic".to_string();
        assert!(message.validate().is_ok());
    }

    #[test]
    fn test_message_expiry() {
        let mut metadata = MessageMetadata::new("test.topic");
        assert!(!metadata.is_expired());
        
        metadata.attributes.expires_at = Some(Utc::now() - chrono::Duration::minutes(1));
        assert!(metadata.is_expired());
    }

    #[test]
    fn test_retry_logic() {
        let mut metadata = MessageMetadata::new("test.topic");
        metadata.attributes.max_retries = 3;
        
        assert!(metadata.can_retry());
        assert_eq!(metadata.attributes.retry_count, 0);
        
        metadata.increment_retry();
        assert_eq!(metadata.attributes.retry_count, 1);
        assert!(metadata.can_retry());
        
        metadata.attributes.retry_count = 3;
        assert!(!metadata.can_retry());
    }
}